/**
 * 
 */
package org.ccay.excel.importer.service.impl.internal;

import java.util.List;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;

import org.ccay.core.exception.ApplicationException;
import org.ccay.core.ioc.Ccay;
import org.ccay.core.log.ILogger;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.excel.exception.ExcelApplicationException;
import org.ccay.excel.exception.ExcelImportException;
import org.ccay.excel.importer.AbstractExcelDataProcessor;
import org.ccay.excel.importer.ExcelImportConstants;
import org.ccay.excel.importer.IExcelImportContext;
import org.ccay.excel.importer.service.IExcelDataConsumer;

/**
 * @author chaowangbang
 *
 */
public class ExcelDataConsumer extends AbstractExcelDataProcessor {
	
	/**
	 * 日志记录器
	 */
	private ILogger logger = CcayLoggerFactory.getLogger(ExcelDataConsumer.class);
	/**
	 * 事务管理器
	 */
	private PlatformTransactionManager transactionManager;
	
	/**
	 * 构造函数
	 */
	public ExcelDataConsumer() {
		this.transactionManager = getTransactionManager();
		
		Assert.notNull(this.transactionManager);
	}

	/* (non-Javadoc)
	 * @see org.ccay.excel.importer.service.impl.internal.IExcelDataProcessor#process(org.ccay.excel.importer.service.impl.internal.ExcelParseContext)
	 */
	public List<?> process(List<?> datas, IExcelImportContext context)
			throws ExcelApplicationException {
		if(datas==null || datas.isEmpty()) {
			return null;
		}
		
		// 获取最终的数据消费者
		IExcelDataConsumer dataConsumer = context.getCurrentDataConsumer();
		
		// 事务定义
		DefaultTransactionDefinition transDef = new DefaultTransactionDefinition();
		transDef.setName("Excel Import");
		// 设置事务传播级别
		transDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		
		TransactionStatus transStatus = null;
		if (this.isTransaction(context)) {
			transStatus = transactionManager.getTransaction(transDef);
		}
		int importSize = 0;
		try {
			// 消费数据
			importSize = dataConsumer.useBatchData(datas, context);
			// 提交事务
			if (this.isTransaction(context)) {
				transactionManager.commit(transStatus);
			}
			context.addImportedCount(importSize);
		} catch (ApplicationException e) {
			logger.error(e);
			// 发生异常后回滚并返回
			if (this.isTransaction(context)) {
				transactionManager.rollback(transStatus);
			}
			throw new ExcelImportException(e.getErrorCode(),e);
		}catch (RuntimeException ex) {
			logger.error("The error occured during invoking sheet with name ["+context.getCurrentSheet().getName() + "]",ex);
			// 发生异常后回滚并返回
			if (this.isTransaction(context)) {
				transactionManager.rollback(transStatus);
			}
			throw new ExcelImportException(ExcelImportConstants.DATACONSUMER_EXCEPTION,context.getCurrentSheet().getName(),ex);
		}catch (Error er) {
			logger.error("The error occured during invoking sheet with name ["+context.getCurrentSheet().getName() + "]",er);
			// 发生异常后回滚并返回
			if (this.isTransaction(context)) {
				transactionManager.rollback(transStatus);
			}
			throw new ExcelImportException(ExcelImportConstants.DATACONSUMER_EXCEPTION,context.getCurrentSheet().getName(),er);
		}  
		return null;
	}
	
	/**
	 * 是否开启事务
	 * @param context
	 * @return
	 */
	private boolean isTransaction(IExcelImportContext context) {
		if ("1".equals(context.getExcelMeta().getNoTransaction())) {
			return false;
		} else {
			return true;
		}
	}
	
	/** 
	 * 获取平台事务管理器
	 * 	
	 * @author chaowangbang
	 * @since Mar 23, 2012
	 * @return
	 */
	private PlatformTransactionManager getTransactionManager() {
		return Ccay.getContext().getBean("txManager",PlatformTransactionManager.class);
	}

}
